# -*- coding: utf-8 -*-
# @Time: 2021/9/7 22:04
# @Author: yuan hao
# @Remark: 视频分析
import logging

from evaluateApi import *
from mxsoftpy.exception import DataError

from utils.classes.custom_exception import ConnectionURLError, MethodExecError


class VideoAnalyze:

    def __init__(self):
        self._handle_dict = dict()  # 存放所有打开的句柄

    def __del__(self):
        """
        退出时释放所有句柄
        """
        for k in self._handle_dict.keys():
            py_releaseFrame(k)

    def _put_handle(self, handle: object) -> None:
        """
        新建句柄
        """
        if len(self._handle_dict) <= 2048:
            self._handle_dict[handle] = 1
        else:
            first_handle = next(iter(self._handle_dict))
            py_releaseFrame(first_handle)
            self._handle_dict.pop(first_handle)
            self._handle_dict[handle] = 1

    def pop_handle(self, handle: object) -> None:
        """
        释放句柄
        """
        py_releaseFrame(handle)
        self._handle_dict.pop(handle)

    def fetch_url(self, url: str) -> object:
        """
        从url中取一帧画面
        """
        try:
            handle_obj, error = py_getSingleFrame(url)
        except Exception:
            raise DataError('从rtsp获取图像失败')
        if error:
            logging.error('从url中获取画面出错, 摄像头url: %s, 错误信息: %s' % (url, error))
            raise ConnectionURLError(error)
        self._put_handle(handle_obj)

        return handle_obj

    def fetch_file(self, filename: str) -> object:
        """
        从文件中取画面
        """

        handle_obj = py_getFrameFromFile(filename)

        self._put_handle(handle_obj)

        return handle_obj

    @staticmethod
    def exec_fun(func_name: str, *args, **kwargs) -> float:
        """
        执行函数
        :param func_name: 函数名称
        """
        try:
            res_float = eval(func_name)(*args, **kwargs)
        except Exception as e:
            logging.error('执行视频质量分析监测函数发生错误：%s，错误详情：%s' % (func_name, str(e)))
            raise MethodExecError(func_name, '无法执行此方法')
        return res_float
